package learnsicp;

/**
 * 阶乘的实现方法
 * @author zc
 *
 */
public class FactorialDemo {

	public static void main(String[] args) {
		System.out.println(factorial1(1));
		System.out.println(factorial2(1));
		System.out.println(factorial3(1));

		System.out.println(factorial1(6));
		System.out.println(factorial2(6));
		System.out.println(factorial3(6));
	}

	/*
	 * 递归计算
	 * 
	 * factorial1(6)
	 * 6 * factorial1(5))
	 * 6 * (5 * factorial1(4))
	 * 6 * (5 * (4 * factorial1(3)))
	 * 6 * (5 * (4 * (3 * factorial1(2))))
	 * 6 * (5 * (4 * (3 * (2 * factorial1(1)))))
	 * 6 * (5 * (4 * (3 * (2 * 1))))
	 * 6 * (5 * (4 * (3 * 2)))
	 * 6 * (5 * (4 * 6))
	 * 6 * (5 * 24)
	 * 6 * 120
	 * 720
	 */
	public static int factorial1(int n) {
		return n == 1 ? n : n * factorial1(n - 1);
	}

	/*
	 * 迭代计算
	 * 
	 * factorial2(6)
	 * 		product = 1 * 1 -> 1
	 *  	product = 1 * 2 -> 2
	 *   	product = 2 * 3 -> 6
	 *    	product = 6 * 4 -> 24
	 *     	product = 24 * 5 -> 120
	 *      product = 120 * 6 -> 720
	 * 	720
	 */
	public static int factorial2(int n) {
		int product = 1;
		for (int i = 1; i <= n; i++) {
			product = product * i;
		}
		return product;
	}

	/*
	 * 递归形式实现迭代计算
	 * 
	 * factorial3(6)
	 * 		factIter(1, 1, 6)
	 * 		factIter(1, 2, 6)
	 * 		factIter(2, 3, 6)
	 * 		factIter(6, 4, 6)
	 * 		factIter(24, 5, 6)
	 * 		factIter(120, 6, 6)
	 * 		factIter(720, 7, 6)
	 * 720
	 */
	public static int factorial3(int n) {
		return factIter(1, 1, n);
	}

	private static int factIter(int product, int counter, int maxCount) {
		if (counter > maxCount) {
			return product;
		}
		return factIter(counter * product, counter + 1, maxCount);
	}

}

